package org.springframework.aop.framework.autoproxy;

import com.springlearn.springsourcecode.chap14.Target;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.Order;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @author wtcode
 * @Description
 * @date 2025/4/9 - 9:01
 */
public class A17 {

    public static void main(String[] args) {

        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("aspect1",Aspect1.class);
        context.registerBean("config",Config.class);
        context.registerBean(ConfigurationClassPostProcessor.class);
        context.registerBean(AnnotationAwareAspectJAutoProxyCreator.class);
        // BeanPostProcessor
        // 创建 -> （*）依赖注入 -> 初始化（*）
        context.refresh();

        /*String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }*/

        /*
         * 第一个重要方法findEligibleAdvisors找到有资格的Advisors
         *
         *
         *
         */
        AnnotationAwareAspectJAutoProxyCreator creator = context.getBean(AnnotationAwareAspectJAutoProxyCreator.class);
        List<Advisor> advisors = creator.findEligibleAdvisors(Target1.class, "target1");
        for (Advisor advisor : advisors) {
            System.out.println(advisor);
        }

        /*
         * 第二个重要方法 wrapIfNecessory
         * 它内部调用findEligibleAdvisors，只要返回集合不为空，则表示需要创建代理
         */

        Object o1 = creator.wrapIfNecessary(new Target1(), "target1", "target1");
        Object o2 = creator.wrapIfNecessary(new Target2(), "target2", "target2");

        ((Target1)o1).foo();


    }

    static class Target1{
        public void foo(){
            System.out.println("target1 foo...");
        }


    }
    static class Target2{
        public void bar(){
            System.out.println("target2 bar...");
        }
    }

    @Aspect
    @Order(1)
    static class Aspect1{
        @Before("execution(* foo())")
        public void before(){
            System.out.println("aspect1 before...");
        }

        @After("execution(* foo())")
        public void after(){
            System.out.println("aspect1 after...");
        }
    }

    @Configuration
    static class Config{
        @Bean
        public Advisor advisor3(MethodInterceptor advice3){
            AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
            pointcut.setExpression("execution(* foo())");
            DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice3);
            advisor.setOrder(2);
            return advisor;
        }
        @Bean
        public MethodInterceptor advice3(){
            return new MethodInterceptor() {
                @Override
                public Object invoke(MethodInvocation invocation) throws Throwable {
                    System.out.println("advice3 before");
                    Object result = invocation.proceed();
                    System.out.println("advice3 after");
                    return result;
                }
            };
        }
    }

}
